//
//  NSDictionary+SafeObject.m
//  iBIMiPhone
//
//  Created by yuebin on 2018/11/20.
//  Copyright © 2018年 ysg. All rights reserved.
//

#import "NSDictionary+SafeObject.h"

@implementation NSDictionary (SafeObject)

- (BOOL)objIsNull {
    return (self == nil || [self isEqual:[NSNull null]]) ? YES : NO;
}

+ (BOOL)objIsNull:(id)obj {
    return (obj == nil || [obj isEqual:[NSNull null]]) ? YES : NO;
}

- (NSInteger)safeIntForKey:(NSString *)key {
    
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return -1;
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"(字典）key非法");
        return -1;
    }
    
    id value = [self objectForKey:key];
    if ([value isKindOfClass:[NSString class]]) {
        return ((NSString *)value).intValue;
    }
    
    if ([value isKindOfClass:[NSNumber class]]) {
        return ((NSNumber *)value).integerValue;
    }
    if ([value isKindOfClass:NSNull.class]) {
        return 0;
    }
    return -1;
}

- (NSString *)safeStringForKey:(NSString *)key {
    
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return @"";
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"（string）key非法");
        return @"";
    }
    
    NSString *value = [self objectForKey:key];
    if ([value isKindOfClass:[NSNumber class]]) {
        return ((NSNumber *)value).stringValue;
    }
    
    if ([value isKindOfClass:[NSString class]] && (value != nil) ) {
        return value;
    }
    return @"";
}

- (NSDictionary *)safeDictionaryForKey:(NSString *)key {
    
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return @{};
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"（字典）key非法");
        return @{};
    }
    
    NSDictionary *value = [self objectForKey:key];
    if ([value isKindOfClass:[NSDictionary class]] && (value != nil)) {
        return value;
    }
    return @{};
}

- (BOOL)safeBoolForKey:(NSString *)key {
    
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return NO;
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"（bool）key非法");
        return NO;
    }
    
    NSString *value = [self objectForKey:key];
    if ((value != nil) || [value isKindOfClass:[NSString class]]) {
        return value.boolValue;
    }
    return NO;
}

- (float)safeFloatForKey:(NSString *)key {
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return 0.0f;
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"(float）key非法");
        return 0.0f;
    }
    
    id value = [self objectForKey:key];
    if ([value isKindOfClass:[NSString class]]) {
        return ((NSString *)value).floatValue;
    }
    
    if ([value isKindOfClass:[NSNumber class]]) {
        return ((NSNumber *)value).floatValue;
    }
    return 0.0f;
}

- (NSURL *)safeUrlForKey:(NSString *)key {
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return [NSURL URLWithString:@""];
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"（url）key非法");
        return [NSURL URLWithString:@""];
    }
    
    NSString *value = [self objectForKey:key];
    if ((value != nil) && [value isKindOfClass:[NSString class]]) {
        NSString *url = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        return [NSURL URLWithString:url];
    }
    return [NSURL URLWithString:@""];
}

- (NSArray *)safeArrayForKey:(NSString *)key {
    if ([self objIsNull] || ![self isKindOfClass:[NSDictionary class]]) {
        NSLog(@"字典非法");
        return @[];
    }
    
    if ([NSDictionary objIsNull:key] || ![key isKindOfClass:[NSString class]]) {
        NSLog(@"（array）key非法");
        return @[];
    }
    
    NSArray *value = [self objectForKey:key];
    if ((value != nil) && [value isKindOfClass:[NSArray class]]) {
        return value;
    }
    return @[];
}


@end
@implementation NSObject (Swizzling)
//#ifdef DEBUG
//#else
+ (BOOL)gl_swizzleMethod:(SEL)origSel withMethod:(SEL)altSel {
    Method origMethod = class_getInstanceMethod(self, origSel);
    Method altMethod = class_getInstanceMethod(self, altSel);
    if (!origMethod || !altMethod) {
        return NO;
    }
    class_addMethod(self,
                    origSel,
                    class_getMethodImplementation(self, origSel),
                    method_getTypeEncoding(origMethod));
    class_addMethod(self,
                    altSel,
                    class_getMethodImplementation(self, altSel),
                    method_getTypeEncoding(altMethod));
    method_exchangeImplementations(class_getInstanceMethod(self, origSel),
                                   class_getInstanceMethod(self, altSel));
    return YES;
}

+ (BOOL)gl_swizzleClassMethod:(SEL)origSel withMethod:(SEL)altSel {
    return [object_getClass((id)self) gl_swizzleMethod:origSel withMethod:altSel];
}

//#endif
@end


@implementation NSDictionary (NilSafe)
//#ifdef DEBUG
//#else
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self gl_swizzleMethod:@selector(initWithObjects:forKeys:count:) withMethod:@selector(gl_initWithObjects:forKeys:count:)];
        [self gl_swizzleClassMethod:@selector(dictionaryWithObjects:forKeys:count:) withMethod:@selector(gl_dictionaryWithObjects:forKeys:count:)];
    });
}

+ (instancetype)gl_dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key || !obj) {
            continue;
        }
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    return [self gl_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j];
}

- (instancetype)gl_initWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key || !obj) {
            continue;
        }
        if (!obj) {
            obj = [NSNull null];
        }
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    return [self gl_initWithObjects:safeObjects forKeys:safeKeys count:j];
}
//#endif

@end


@implementation NSMutableDictionary (NilSafe)

//#ifdef DEBUG
//#else
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class1 = NSClassFromString(@"__NSDictionaryM");
        [class1 gl_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(gl_setObject:forKey:)];
        [class1 gl_swizzleMethod:@selector(setObject:forKeyedSubscript:) withMethod:@selector(gl_setObject:forKeyedSubscript:)];
    });
}

- (void)gl_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    if (!aKey || !anObject) {
        return;
    }
    [self gl_setObject:anObject forKey:aKey];
}

- (void)gl_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
    if (!key || !obj) {
        return;
    }
    [self gl_setObject:obj forKeyedSubscript:key];
}
//#endif

@end
